#!/bin/sh


if [ -n "$_VL_IMPORT_STEP_COMPILE" ] ; then
	return 0;
fi
_VL_IMPORT_STEP_COMPILE=0

# 加载项目环境
if ! load "$VL_ENV" ; then
	return 1;
fi

# 编译程序
#
# 返回值 : 编译成功返回 0
function compile() {
	# 加载 autogen 脚本
	if ! load "$VL_ENV_PART_STEP_FOR_GEN" ; then
		return 1
	fi

	if isVLStyleProject && ! checkVariable "$VL_ARG_COMPILE_MODE" ; then
		if ! compileDep ; then
			return 1
		fi
	fi


	# 普通编译模式不进行依赖检查
	# 构建编译脚本
	if ! makeConfigureCommand ; then
		printError "make configure command failed ... "
		return 1
	fi

	# 先进行 autogen
	if ! checkAutoGen ; then
		return 1
	fi

	# 准备就绪, 进行编译
	
	cd "$VL_DIR_ROOT"

	# 读取编译缓存文件
	local shouldConfig=0
	local shouldMake=0

	if checkVariable "$VL_ARG_COMPILE_TEST" ; then
		# 测试模式下, 每次都会重新执行一遍 make
		shouldMake=1
	fi

	if checkFile "$VL_CACHE_FILE_COMPILE" ; then
		# 存在编译缓存文件, 判断本次是否应该进行 configure or make
		if readProps "$VL_CACHE_FILE_COMPILE" "VL_COMPILE_CACHE_TOOLCHAIN_FILE" \
			"VL_COMPILE_CACHE_TOOLCHAIN_TS" "VL_COMPILE_CACHE_OPTIONS_TS" "VL_COMPILE_CACHE_DEP_OPTIONS_TS" \
			"VL_COMPILE_CACHE_AS_DEP" "VL_COMPILE_CACHE_PREFIX" ; then
			if [[ "$VL_COMPILE_CONFIG_ARGS_PREFIX" != "$VL_COMPILE_CACHE_PREFIX" ]] ; then
				shouldConfig=1
				shouldMake=1
			fi
			if checkVariable "$VL_ARG_COMPILE_AS_DEP" && [[ "$VL_ARG_COMPILE_AS_DEP" != "$VL_COMPILE_CACHE_AS_DEP" ]] ; then
				shouldMake=1
			fi
			if checkVariable "$VL_ARG_COMPILE_TOOLCHAIN" ; then
				# 指定 toolchain 文件
				# 比对 toolchain 文件路径和时间戳
				local fileTs=$(date -r "$VL_ARG_COMPILE_TOOLCHAIN" +%s)
				if [[ "$VL_COMPILE_CACHE_TOOLCHAIN_FILE" != "$VL_ARG_COMPILE_TOOLCHAIN" ]] || [[ "$VL_COMPILE_CACHE_TOOLCHAIN_TS" != "$fileTs" ]] ; then
					# toolchain 文件变化
					shouldConfig=1
					shouldMake=1
				fi
			else
				if checkVariable "$VL_COMPILE_CACHE_TOOLCHAIN_FILE" || checkVariable "$VL_COMPILE_CACHE_TOOLCHAIN_TS" ; then
					# 本次编译没有指定 toolchain, 但上次编译存在 toolchain
					shouldConfig=1
					shouldMake=1
				fi
			fi

			if checkFile "$VL_FILE_COMPILE_OPTIONS" ; then
				# 如果存在 vl_compile_options.sh 文件
				local fileCurrentTs=$(date -r "$VL_FILE_COMPILE_OPTIONS" +%s)
				if [[ "$fileCurrentTs" != "$VL_COMPILE_CACHE_OPTIONS_TS" ]] ; then
					# 配置文件发生变化
					shouldConfig=1
					shouldMake=1
				fi
			elif checkVariable "$VL_COMPILE_CACHE_OPTIONS_TS" ; then
				# 如果不存在 vl_compile_options.sh 文件, 但上次编译存在 ts 属性
				shouldConfig=1
				shouldMake=1
			fi

			if checkFile "$VL_CACHE_FILE_DEP_OPTIONS" ; then
				# 如果存在 vl_dep_compile_options 文件
				local fileCurrentTs=$(date -r "$VL_CACHE_FILE_DEP_OPTIONS" +%s)
				if [[ "$fileCurrentTs" != "$VL_COMPILE_CACHE_DEP_OPTIONS_TS" ]] ; then
					# 配置文件发生变化
					shouldConfig=1
					shouldMake=1
				fi
			elif checkVariable "$VL_COMPILE_CACHE_DEP_OPTIONS_TS" ; then
				# 如果不存在 vl_dep_compile_options 文件, 但上次编译存在 ts 属性
				shouldConfig=1
				shouldMake=1
			fi
		else
			printError "borken cache file: $VL_CACHE_FILE_COMPILE"
			return 1
		fi
	else
		shouldConfig=1
		shouldMake=1
	fi

	if [ "$shouldConfig" -eq 1 ] ; then
		if ! eval "$VL_COMPILE_CONFIG_COMMAND" ; then
			printError "configure error ..."
			return 1
		fi
	fi

	if [ "$shouldConfig" -eq 1 ] || [ "$shouldMake" -eq 1 ] ; then
		if ! make ; then
			printError "make error ..."
			return 1
		fi

		if ! make install ; then
			printError "make error ..."
			return 1
		fi

		local genDir=
		local staticDir=
		if [[ "$VL_OS_TYPE" -eq "$VL_OS_TYPE_MACOS" ]] ; then
			# 如果是 Macos 系统, 需要额外生成一个静态目录方便静态链接
			if checkVariable "$VL_COMPILE_CONFIG_ARGS_PREFIX" ; then
				# 指定目录
				genDir="$VL_COMPILE_CONFIG_ARGS_PREFIX/lib"
				staticDir="$VL_COMPILE_CONFIG_ARGS_PREFIX/slib"
			else
				# 未指定目录
				genDir="/usr/local/lib"
				staticDir="/usr/local/slib"
			fi
		fi

		if checkDir "$genDir" && checkVariable "$staticDir" ; then
			if ! checkDirOrCreate "$staticDir" ; then
				printError "create \"$staticDir\" dir failed..."
				return 1
			fi
			
			eval cp -in "$genDir/*.a" "$staticDir"
		fi

	fi

	# 确认 .vl-build 文件夹是否创建
	if ! checkDirOrCreate "$VL_DIR_BUILD" ; then
		printError "create \"$VL_DIR_BUILD\" failed."
		return 1
	fi

	# 生成编译缓存文件
	if ! load "$VL_ENV_PART_GENERATE_FOR_COMPILE" ; then
		return 1
	fi


	VL_COMPILE_CACHE_TOOLCHAIN_FILE="$VL_ARG_COMPILE_TOOLCHAIN"
	if checkFile "$VL_ARG_COMPILE_TOOLCHAIN" ; then
		VL_COMPILE_CACHE_TOOLCHAIN_TS="$(date -r "$VL_ARG_COMPILE_TOOLCHAIN" +%s)"
	else
		VL_COMPILE_CACHE_TOOLCHAIN_TS=
	fi
	if checkFile "$VL_FILE_COMPILE_OPTIONS" ; then
		VL_COMPILE_CACHE_OPTIONS_TS="$(date -r "$VL_FILE_COMPILE_OPTIONS" +%s)"
	else
		VL_COMPILE_CACHE_OPTIONS_TS=
	fi
	if checkFile "$VL_CACHE_FILE_DEP_OPTIONS" ; then
		VL_COMPILE_CACHE_DEP_OPTIONS_TS="$(date -r "$VL_CACHE_FILE_DEP_OPTIONS" +%s)"
	else
		VL_COMPILE_CACHE_DEP_OPTIONS_TS=
	fi
	
	VL_COMPILE_CACHE_AS_DEP="$VL_ARG_COMPILE_AS_DEP"
	if ! generateCompileCache "$VL_CACHE_FILE_COMPILE" ; then
		printError "create \"$VL_CACHE_FILE_COMPILE\" failed."
		return 1
	fi

	# 如果是测试模式, 执行可执行文件
	if checkVariable "$VL_ARG_COMPILE_TEST" ; then
		case "$VL_TYPE" in
		lib)
			eval "$VL_DIR_ROOT/vl_test_build/bin/test_program"
		;;
		exec)
			eval "$VL_DIR_ROOT/vl_test_build/bin/$VL_NAME"
		;;
		esac
	fi

	return 0
}

# 仅编译依赖程序
#
# 返回值 : 编译成功返回 0
function compileDep() {
	if ! isVLStyleProject ; then
		printWarn "$VL_DIR_ROOT is not a vl-style project, ignore ..."
		return 0
	fi

	if checkFile "$VL_CACHE_FILE_DEP_COMPILE_LIST" ; then
		# 存在依赖项目
		while read line
		do
			local depsArr=($line)
			if [ "${#depsArr[@]}" -ne 2 ] ; then
				printError "Unknown dependency : ${depsArr[*]}"
				return 1
			fi

			if ! checkDir "$VL_DIR_DEP/${depsArr[0]}" ; then
				printError "Not found dependency : $VL_DIR_DEP/${depsArr[0]}"
				return 1
			fi

			echo "compiling ${depsArr[0]} ..."
			# 编译依赖项目
			if checkVariable "$VL_ARG_COMPILE_TOOLCHAIN" ; then
				# 存在编译工具链文件
				if ! eval "$VL_ENV_BUILD compile -tool \"$VL_ARG_COMPILE_TOOLCHAIN\" -as-dep \"$VL_DIR_DEP/${depsArr[0]}\"" ; then
					printError "compile ${depsArr[0]} error ..."
					return 1
				fi
			else
				# 不存在编译工具链文件
				echo "$VL_ENV_BUILD compile -as-dep \"$VL_DIR_DEP/${depsArr[0]}\""
				if ! eval "$VL_ENV_BUILD compile -as-dep \"$VL_DIR_DEP/${depsArr[0]}\"" ; then
					printError "compile ${depsArr[0]} error ..."
					return 1
				fi
			fi
		done < "$VL_CACHE_FILE_DEP_COMPILE_LIST"
	fi

	return 0
}

# 构建 Configure 指令
#
# 返回值 : 构建成功返回 0
function makeConfigureCommand() {
	VL_COMPILE_CONFIG_COMMAND="./configure"
	# 先检查工程项目下有无 vl_dep_compile_options
	if checkFile "$VL_FILE_COMPILE_OPTIONS" ; then
		# 存在, 读取参数
		if ! readProps "$VL_FILE_COMPILE_OPTIONS" "VL_CONFIG_ARGS_CXXFLAGS" \
			"VL_CONFIG_ARGS_LIBS" "VL_CONFIG_ARGS_LDFLAGS" \
			 "VL_CONFIG_ARGS_CPPFLAGS" "VL_CONFIG_ARGS_CFLAGS" \
			 "VL_CONFIG_ARGS_LT_SYS_LIBRARY_PATH" "VL_CONFIG_ARGS_CXXCPP" ; then
			 return 1
		fi

		defineVar "VL_COMPILE_CONFIG_ARGS_CXXFLAGS" "$VL_CONFIG_ARGS_CXXFLAGS" "2"
		defineVar "VL_COMPILE_CONFIG_ARGS_LIBS" "$VL_CONFIG_ARGS_LIBS" "2"
		defineVar "VL_COMPILE_CONFIG_ARGS_LDFLAGS" "$VL_CONFIG_ARGS_LDFLAGS" "2"
		defineVar "VL_COMPILE_CONFIG_ARGS_CPPFLAGS" "$VL_CONFIG_ARGS_CPPFLAGS" "2"
		defineVar "VL_COMPILE_CONFIG_ARGS_CFLAGS" "$VL_CONFIG_ARGS_CFLAGS" "2"
		defineVar "VL_COMPILE_CONFIG_ARGS_LT_SYS_LIBRARY_PATH" "$VL_CONFIG_ARGS_LT_SYS_LIBRARY_PATH" "2"
		defineVar "VL_COMPILE_CONFIG_ARGS_CXXCPP" "$VL_CONFIG_ARGS_CXXCPP" "2"
	fi

	if checkFile "$VL_CACHE_FILE_DEP_OPTIONS" ; then
		if ! readProps "$VL_CACHE_FILE_DEP_OPTIONS" "VL_CONFIG_ARGS_PREFIX" \
			"VL_CONFIG_ARGS_LIBS" "VL_CONFIG_ARGS_LDFLAGS" "VL_CONFIG_ARGS_CPPFLAGS" ; then
			return 1
		fi

		defineVar "VL_COMPILE_CONFIG_ARGS_PREFIX" "$VL_CONFIG_ARGS_PREFIX"
		defineVar "VL_COMPILE_CONFIG_ARGS_LIBS" "$VL_CONFIG_ARGS_LIBS" "2"
		defineVar "VL_COMPILE_CONFIG_ARGS_LDFLAGS" "$VL_CONFIG_ARGS_LDFLAGS" "2"
		defineVar "VL_COMPILE_CONFIG_ARGS_CPPFLAGS" "$VL_CONFIG_ARGS_CPPFLAGS" "2"
	fi

	if checkVariable "$VL_ARG_COMPILE_TOOLCHAIN" ; then
		# 如果存在 toolchains 文件
		if ! readProps "$VL_ARG_COMPILE_TOOLCHAIN" "VL_CONFIG_ARGS_SYSROOT" "VL_CONFIG_ARGS_HOST" \
			"VL_CONFIG_ARGS_BUILD" "VL_CONFIG_ARGS_CC" "VL_CONFIG_ARGS_CXX" \
			"VL_CONFIG_ARGS_AR" "VL_CONFIG_ARGS_RANLIB" ; then
			return 1
		fi

		defineVar "VL_CONFIG_ARGS_SYSROOT" "$VL_CONFIG_ARGS_SYSROOT"
		defineVar "VL_CONFIG_ARGS_HOST" "$VL_CONFIG_ARGS_HOST"
		defineVar "VL_CONFIG_ARGS_BUILD" "$VL_CONFIG_ARGS_BUILD"
		defineVar "VL_CONFIG_ARGS_CC" "$VL_CONFIG_ARGS_CC"
		defineVar "VL_CONFIG_ARGS_CXX" "$VL_CONFIG_ARGS_CXX"
		defineVar "VL_CONFIG_ARGS_AR" "$VL_CONFIG_ARGS_AR"
		defineVar "VL_CONFIG_ARGS_RANLIB" "$VL_CONFIG_ARGS_RANLIB"
	fi


	if checkVariable "$VL_ARG_COMPILE_TEST" ; then
		if ! isVLStyleProject ; then
			printError "Only vl-style project support \"-t/--test\" argument"
			return 1
		fi
		# 编译测试程序
		# 强行覆盖 prefix
		VL_COMPILE_CONFIG_ARGS_PREFIX="$VL_DIR_ROOT/vl_test_build"
		case "$VL_TYPE" in
		lib)
			VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND --enable-test-program=yes"
		;;
		exec)
		;;
		*)
			printError "unsupported project type: $VL_TYPE"
			return 1
		;;
		esac
	fi

	if checkVariable "$VL_COMPILE_CONFIG_ARGS_PREFIX" ; then
		VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND --prefix=\"$VL_COMPILE_CONFIG_ARGS_PREFIX\""
	fi

	if checkVariable "$VL_COMPILE_CONFIG_ARGS_SYSROOT" ; then
		VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND --with-sysroot=\"$VL_COMPILE_CONFIG_ARGS_SYSROOT\""
	fi

	if checkVariable "$VL_COMPILE_CONFIG_ARGS_HOST" ; then
		VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND --host=\"$VL_COMPILE_CONFIG_ARGS_HOST\""
	fi

	if checkVariable "$VL_COMPILE_CONFIG_ARGS_BUILD" ; then
		VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND --build=\"$VL_COMPILE_CONFIG_ARGS_BUILD\""
	fi

	if checkVariable "$VL_COMPILE_CONFIG_ARGS_CC" ; then
		VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND CC=\"$VL_COMPILE_CONFIG_ARGS_CC\""
	fi

	if checkVariable "$VL_COMPILE_CONFIG_ARGS_CXX" ; then
		VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND CXX=\"$VL_COMPILE_CONFIG_ARGS_CXX\""
	fi

	if checkVariable "$VL_COMPILE_CONFIG_ARGS_AR" ; then
		VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND AR=\"$VL_COMPILE_CONFIG_ARGS_AR\""
	fi

	if checkVariable "$VL_COMPILE_CONFIG_ARGS_RANLIB" ; then
		VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND RANLIB=\"$VL_COMPILE_CONFIG_ARGS_RANLIB\""
	fi

	if checkVariable "$VL_COMPILE_CONFIG_ARGS_CXXFLAGS" ; then
		VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND CXXFLAGS=\"$VL_COMPILE_CONFIG_ARGS_CXXFLAGS\""
	fi

	if checkVariable "$VL_COMPILE_CONFIG_ARGS_LIBS" ; then
		VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND LIBS=\"$VL_COMPILE_CONFIG_ARGS_LIBS\""
	fi

	if checkVariable "$VL_COMPILE_CONFIG_ARGS_LDFLAGS" ; then
		VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND LDFLAGS=\"$VL_COMPILE_CONFIG_ARGS_LDFLAGS\""
	fi

	if checkVariable "$VL_COMPILE_CONFIG_ARGS_CPPFLAGS" ; then
		VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND CPPFLAGS=\"$VL_COMPILE_CONFIG_ARGS_CPPFLAGS\""
	fi

	if checkVariable "$VL_COMPILE_CONFIG_ARGS_CFLAGS" ; then
		VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND CFLAGS=\"$VL_COMPILE_CONFIG_ARGS_CFLAGS\""
	fi

	if checkVariable "$VL_COMPILE_CONFIG_ARGS_LT_SYS_LIBRARY_PATH" ; then
		VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND LT_SYS_LIBRARY_PATH=\"$VL_COMPILE_CONFIG_ARGS_LT_SYS_LIBRARY_PATH\""
	fi

	if checkVariable "$VL_COMPILE_CONFIG_ARGS_CXXCPP" ; then
		VL_COMPILE_CONFIG_COMMAND="$VL_COMPILE_CONFIG_COMMAND CXXCPP=\"$VL_COMPILE_CONFIG_ARGS_CXXCPP\""
	fi

	echo "$VL_COMPILE_CONFIG_COMMAND"
}